package com.swing.jiaocheng;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

/**
 * Swing事件监听：事件处理模型和事件监听器
 */
public class ActionListenerDemo13 extends JFrame{
    private static int clicks;
    /**
     * 事件表示程序和用户之间的交互，例如在文本框中输入，在列表框或组合框中选择，选中复选框和单选框，单击按钮等。事件处理表示程序对事件的响应，对用户的交互或者说对事件的处理是事件处理程序完成的。
     *
     * 当事件发生时，系统会自动捕捉这一事件，创建表示动作的事件对象并把它们分派给程序内的事件处理程序代码。这种代码确定了如何处理此事件以使用户得到相应的回答。
     * 事件处理模型
     * 前面我们讲解了如何放置各种组件，使图形界面更加丰富多彩，但是还不能响应用户的任何操作。若使图形界面能够接收用户的操作，必须给各个组件加上事件处理机制。在事件处理的过程中，主要涉及三类对象。
     * Event（事件）：用户对组件的一次操作称为一个事件，以类的形式出现。例如，键盘操作对应的事件类是 KeyEvent。
     * Event Source（事件源）：事件发生的场所，通常就是各个组件，例如按钮 Button。
     * Event Handler（事件处理者）：接收事件对象并对其进行处理的对象事件处理器，通常就是某个 Java 类中负责处理事件的成员方法。
     *
     * 例如，如果鼠标单击了按钮对象 Button，则该按钮 Button 就是事件源，而 Java 运行时系统会生成 ActionEvent 类的对象 ActionEvent，该对象中描述了单击事件发生时的一些信息。之后，事件处理者对象将接收由 Java 运行时系统传递过来的事件对象 ActionEvent，并进行相应的处理。事件处理模型如图 1 所示。
     *
     * 事件处理模型
     * 图1 事件处理模型
     *
     * 由于同一个事件源上可能发生多种事件，因此，Java 采取了授权模型（Delegation Model），事件源可以把在其自身上所有可能发生的事件分别授权给不同的事件处理者来处理。例如，在 Panel 对象上既可能发生鼠标事件，也可能发生键盘事件，该 Panel 对象可以授权给事件处理者 a 来处理鼠标事件，同时授权给事件处理者 b 来处理键盘事件。
     *
     * 有时也将事件处理者称为监听器，主要原因在于监听器时刻监听事件源上所有发生的事件类型，一旦该事件类型与自己所负责处理的事件类型一致，就马上进行处理。授权模型把事件的处理委托给外部的处理实体进行处理，实现了将事件源和监听器分开的机制。
     *
     * 事件处理者（监听器）通常是一个类，该类如果能够处理某种类型的事件，就必须实现与该事件类型相对的接口。例如，一个 ButtonHandler 类之所以能够处理 ActionEvent 事件，原因在于它实现了与 ActionEvent 事件对应的接口 ActionListener。每个事件类都有一个与之相对应的接口。
     */

    /**
     * 动作事件监听器
     * 动作事件监听器是Swing中比较常用的事件监听器，很多组件的动作都会使用它监听，像按钮被单击，列表框中选择一项等。
     * 事件名称: ActionEvent
     * 事件监听接口: ActionListener
     * 事件相关方法: addActionListener()添加监听，removeActionListener()删除监听
     * 涉及事件源: JButton,JList,JTextField等
     */

    public static void mains(String[] args) {

        JFrame jFrame = new JFrame();
        JList jList = new JList();


        jFrame.setTitle("动作事件监听器");
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setBounds(100, 100, 400, 200);

        JPanel contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));

        jFrame.setContentPane(contentPane);

        JLabel jLabel = new JLabel(" ");
        //修改字体样式
        jLabel.setFont(new Font("楷体", Font.BOLD, 16));

        contentPane.add(jLabel, BorderLayout.SOUTH);
        JButton jButton = new JButton("我是普通按钮");
        jButton.setFont(new Font("黑体", Font.BOLD, 16));
        jButton.addActionListener(e -> {
            jLabel.setText("按钮被单击了" + (clicks++) + "次");
        });

        contentPane.add(jButton);

        jFrame.setVisible(true);

    }


    /**
     * 焦点事件监听器
     * 除了单击事件外，焦点事件监听器在实际项目中应用也比较广泛，例如将光标离开文本框时弹出对话框，或者将焦点返回给文本框等。
     *
     * 与焦点事件监听器有关的信息如下。
     * 事件名称：FocusEvent。
     * 事件监听接口： FocusListener。
     * 事件相关方法：addFocusListener() 添加监听，removeFocusListener() 删除监听。
     * 涉及事件源：Component 以及派生类。
     *
     * FocusEvent 接口定义了两个方法，分别为 focusGained() 方法和 focusLost() 方法，其中 focusGained() 方法是在组件获得焦点时执行，focusLost() 方法是在组件失去焦点时执行。
     */

    public void main(String[] args) {
        JList list;
        JLabel label;
        JButton button1;
        JTextField txtfield1;

        JPanel contentPane=new JPanel();
        contentPane.setBorder(new EmptyBorder(5,5,5,5));
        contentPane.setLayout(new BorderLayout(0,0));
        setContentPane(contentPane);
        label=new JLabel(" ");
        label.setFont(new Font("楷体",Font.BOLD,16));    //修改字体样式
        contentPane.add(label, BorderLayout.SOUTH);
        txtfield1=new JTextField();    //创建文本框
        txtfield1.setFont(new Font("黑体", Font.BOLD, 16));    //修改字体样式
        txtfield1.addFocusListener(new FocusListener()
        {
            @Override
            public void focusGained(FocusEvent arg0)
            {
                // 获取焦点时执行此方法
                label.setText("文本框获得焦点，正在输入内容");
            }
            @Override
            public void focusLost(FocusEvent arg0)
            {
                // 失去焦点时执行此方法
                label.setText("文本框失去焦点，内容输入完成");
            }
        });
        contentPane.add(txtfield1);
    }




}
